package com.wang.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import com.wang.springframework.beans.factory.config.BeanDefinition;
import com.wang.springframework.beans.factory.support.BeanDefinitionRegistry;
import com.wang.springframework.stereotype.Component;

import java.util.Set;

/**
 * @author wangjianhua
 * @Description 一个bean定义的扫描器 在类的路径上扫描等待注入的bean
 * 并在BeanFactory或者ApplicationContext给定的registry中注册相应的beanDefinition
 * @date 2021/9/3/003 17:38
 **/
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String ... basePackages){
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidates) {
                //解析 Bean的作用域 singleton , prototype
                String beanScope = resolveBeanScope(beanDefinition);
                if(StrUtil.isNotEmpty(beanScope)){
                    beanDefinition.setScope(beanScope);
                }
                registry.registryBeanDefinition(determineBeanName(beanDefinition),beanDefinition);
            }
        }
    }

    private String resolveBeanScope(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if(null != scope){
            return scope.value();
        }
        return StrUtil.EMPTY;
    }

    /**
     * 决定一下bean名称
     * @param beanDefinition beanDefinition
     * @return bean名称
     */
    private String determineBeanName(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);
        String value = component.value();
        if(StrUtil.isEmpty(value)){
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }
}
